package com.zts.modules.sys.controller;

import com.zts.base.BasicResourceAssembler;
import com.zts.base.page.PageBound;
import com.zts.base.resource.ListResource;
import com.zts.common.Constant;
import com.zts.modules.sys.entity.Group;
import com.zts.modules.sys.entity.Role;
import com.zts.modules.sys.entity.User;
import com.zts.modules.sys.entity.UserGroupRelation;
import com.zts.modules.sys.entity.model.GroupModel;
import com.zts.modules.sys.entity.resource.GroupResource;
import com.zts.modules.sys.entity.resource.RoleResource;
import com.zts.modules.sys.entity.resource.UserResource;
import com.zts.modules.sys.service.GroupService;
import com.zts.modules.sys.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * Created by lily on 2017/6/7.
 */
@RestController("groupController")
@RequestMapping("/v1/groups")
@Api(value = "groups", description = "组相关API")
@ExposesResourceFor(GroupResource.class)
public class GroupController {
    private static Logger logger = LoggerFactory.getLogger(GroupController.class);
    @Autowired
    GroupService groupService;

    @Autowired
    UserService userService;


    private BasicResourceAssembler<Group, GroupResource> groupAssembler =
            new BasicResourceAssembler<>(GroupController.class, GroupResource.class);
    private BasicResourceAssembler<User, UserResource> userAssembler =
            new BasicResourceAssembler<>(GroupController.class, UserResource.class);
    private BasicResourceAssembler<Role, RoleResource> roleAssembler =
            new BasicResourceAssembler<>(GroupController.class, RoleResource.class);


    //===========================组的增删改查 begin=============================================

    /**
     * 根据查询条件查询组
     *
     * @param groupModel
     * @param pageBound
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "", method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getGroups", httpMethod = "GET", value = "获取组的分页信息")
    public final ListResource<GroupResource> getGroups(@ApiParam(required = false, value = "组的查询条件")
                                                       @ModelAttribute("groupModel") GroupModel groupModel,
                                                       PageBound pageBound) {
        List<Group> list = groupService.getList(groupModel.transEntity(), pageBound);
        return groupAssembler.toListResource(list);
    }


    /**
     * 根据组的id，获取唯一的组。
     * *
     *
     * @param
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getGroup", httpMethod = "GET", value = "根据主键id查询组")
    public final GroupResource getGroup(@ApiParam(required = true, value = "主键id")
                                        @PathVariable("id") Long id) {
        return groupAssembler.toResource(groupService.get(id));
    }

    /**
     * 添加组
     *
     * @param groupModel
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "", method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE,
                    MediaType.APPLICATION_JSON_VALUE},
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "insertGroup", httpMethod = "POST", value = "新增组")
    public final GroupResource insertGroup(@ApiParam("组信息，传送格式为json")
                                           @RequestBody GroupModel groupModel) {
        return groupAssembler.toResource(groupService.insert(groupModel.transEntity()));
    }

    /**
     * 更新组
     *
     * @param id
     * @param groupModel
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE,
                    MediaType.APPLICATION_JSON_VALUE},
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "updateGroupById", httpMethod = "PUT", value = "根据组的主键id更新组")
    public final int updateGroup(@ApiParam(value = "组的主键id", required = true)
                                 @PathVariable("id") Long id,
                                 @ApiParam(value = "要修改的组信息项及对应修改的值，接收数据格式为json", required = true)
                                 @RequestBody GroupModel groupModel) {
        groupModel.setId(id);
        return groupService.update(groupModel.transEntity());
    }

    /**
     * 删除组
     *
     * @param id
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "deleteGroup", httpMethod = "DELETE", value = "根据组的主键id删除组")
    public final int deleteGroup(@ApiParam(value = "组的主键id", required = true, defaultValue = "0")
                                 @PathVariable("id") Long id) {
        Group group = new Group();
        group.setId(id);
        return groupService.delete(group);
    }

    //===========================组的增删改查 end=============================================

    //===========================组的下级查询 begin=============================================

    /**
     * 查询全部部门和用户的组织关系
     *
     * @param
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/withuser", method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getUserAndGroup", httpMethod = "GET", value = "查询全部部门和用户的组织关系")
    public final List<UserGroupRelation> getUserAndGroup() {
        List list = userService.getUserGroup();
        return list;
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/children", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getDirectChildren", httpMethod = "GET", value = "查询组的直接下级组")
    public final ListResource<GroupResource> getChildren(@ApiParam(value = "组的主键id", required = true)
                                                         @PathVariable("id") Long id) {
        List<Group> list = groupService.getChildren(id, "true");
        return groupAssembler.toListResource(list);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/allchildren", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getAllChildren", httpMethod = "GET", value = "查询组的所有下级组（包括间接下级）")
    public final ListResource<GroupResource> getAllChildren(@ApiParam(value = "组的主键id", required = true)
                                                            @PathVariable("id") Long id) {
        List<Group> list = groupService.getChildren(id, "false");
        return groupAssembler.toListResource(list);
    }

    //===========================组的下级查询 end=============================================

    //===========================组与用户 begin=============================================

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getDirectUsers", httpMethod = "GET", value = "查询组下的直接用户")
    public final ListResource<UserResource> getUsers(@ApiParam(value = "组的主键id", required = true)
                                                     @PathVariable("id") Long id) {
        List<User> list = groupService.getUsers(id, "true");
        return userAssembler.toListResource(list);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/allusers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getAllUsers", httpMethod = "GET", value = "查询组下的所有用户(包括间接下级组下的用户)")
    public final ListResource<UserResource> getAllUsers(@ApiParam(value = "组的主键id", required = true)
                                                        @PathVariable("id") Long id) {
        List<User> list = groupService.getUsers(id, "false");
        return userAssembler.toListResource(list);
    }


    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/{id}/users/{userid}", method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "addUserIntoGroup", httpMethod = "POST", value = "将单个用户加入到当前组中")
    public final int addUserIntoGroup(@ApiParam(value = "组的主键id", required = true)
                                      @PathVariable("id") Long groupId,
                                      @ApiParam(value = "要添加的用户主键id", required = true)
                                      @PathVariable("userid") Long userId,
                                      @ApiParam(value = "用户加入组的类型", required = true)
                                      @RequestParam(value = "groupType") String groupType,
                                      @ApiParam(value = "用户在组中的排序",required = false,defaultValue = "0")
                                      @RequestParam(value = "sortNum",required = false,defaultValue = "0") int sortNum) {
        return groupService.addUserIntoGroup(userId, groupId, groupType,sortNum);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/{id}/users", method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "addUsersIntoGroup", httpMethod = "POST", value = "批量将多个用户加入到当前组中")
    public final int addUsersIntoGroup(@ApiParam(value = "组的主键id", required = true)
                                       @PathVariable("id") Long groupId,
                                       @ApiParam(value = "要添加的用户列表，传送格式为JSON", required = true)
                                       @RequestBody List<Long> userIds,
                                       @ApiParam(value = "用户加入组的类型", required = true)
                                       @RequestParam(value = "groupType") String groupType) {
        return groupService.addUsersIntoGroup(userIds, groupId, groupType);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{id}/users/{userid}", method = RequestMethod.DELETE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "deleteUserFromGroup", httpMethod = "DELETE", value = "将单个用户从当前组中删除")
    public final int deleteUserFromGroup(@ApiParam(value = "组的主键id", required = true)
                                         @PathVariable("id") Long groupId,
                                         @ApiParam(value = "要删除的用户主键id", required = true)
                                         @PathVariable("userid") Long userId) {
        return groupService.deleteUserFromGroup(userId, groupId);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{id}/users", method = RequestMethod.DELETE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "deleteUsersFromGroup", httpMethod = "DELETE", value = "批量将多个用户从当前组中删除")
    public final int deleteUsersFromGroup(@ApiParam(value = "组的主键id", required = true)
                                          @PathVariable("id") Long groupId,
                                          @ApiParam(value = "要删除的用户列表，传送格式为JSON", required = true)
                                          @RequestBody List<Long> userIds) {
        return groupService.deleteUsersFromGroup(userIds, groupId);
    }

    //===========================组与用户  end=============================================

    //===========================组与角色  begin=============================================

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/roles", method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getRoles", httpMethod = "GET", value = "查询组的直接授权")
    public final ListResource<RoleResource> getRoles(@ApiParam(value = "组的主键id", required = true)
                                                     @PathVariable("id") Long groupId) {
        return roleAssembler.toListResource(groupService.getRoles(groupId));
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}/allroles", method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "getAllRoles", httpMethod = "GET", value = "查询组的所有授权，包括组的递归上级组拥有的角色")
    public final ListResource<RoleResource> getAllRoles(@ApiParam(value = "组的主键id", required = true)
                                                        @PathVariable("id") Long groupId) {
        return roleAssembler.toListResource(groupService.getAllRoles(groupId));
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/{id}/roles/{roleid}", method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "singleGrant", httpMethod = "POST", value = "机构单一授权")
    public final int singleGrant(@ApiParam(value = "组的主键id", required = true)
                                 @PathVariable("id") Long groupId,
                                 @ApiParam(value = "角色的主键id", required = true)
                                 @PathVariable("roleid") Long roleId,
                                 @ApiParam(value = "授权时需排除在外的用户的主键id列表，传送格式为JSON", required = false)
                                 @RequestBody List<Long> userIds) {
        return groupService.groupGrantExcludeUsers(groupId, roleId, userIds);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @RequestMapping(value = "/{id}/roles", method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "batchGrant", httpMethod = "POST", value = "机构批量授权")
    public final int batchGrant(@ApiParam(value = "组的主键id", required = true)
                                @PathVariable("id") Long groupId,
                                @ApiParam(value = "角色的主键id列表，传送格式为JSON", required = true)
                                @RequestBody List<Long> roleIds) {
        return groupService.batchGrant(groupId, roleIds, "1");
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{id}/roles/{roleid}", method = RequestMethod.DELETE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "singleGrantDelete", httpMethod = "DELETE", value = "组删除单一授权")
    public final int singleGrantDelete(@ApiParam(value = "组的主键id", required = true)
                                       @PathVariable("id") Long groupId,
                                       @ApiParam(value = "角色的主键id", required = true)
                                       @PathVariable("roleid") Long roleId) {
        return groupService.singleGrantDelete(groupId, roleId, Constant.GRANT_TYPE_ASSIGN);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequestMapping(value = "/{id}/roles", method = RequestMethod.DELETE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(notes = "batchGrantDelete", httpMethod = "DELETE", value = "批量删除组的授权")
    public final int batchGrantDelete(@ApiParam(value = "组的主键id", required = true)
                                      @PathVariable("id") Long groupId,
                                      @ApiParam(value = "要删除的角色的主键id列表，传送格式为JSON", required = true)
                                      @RequestBody List<Long> roleIds) {
        return groupService.batchGrantDelete(groupId, roleIds, Constant.GRANT_TYPE_ASSIGN);
    }

    //===========================组与角色  end=============================================
}
